//
//  JCBuilderUtil.swift
//  JCPublicKit
//
//  Created by JasonLee on 2020/5/12.
//

import Foundation

class JCAttributedStringBuilder {
    var text: String?
    
    var attributes: [NSAttributedString.Key : Any] = [:]
    
    var shadow: NSShadow?
    var paragraphStyle: NSMutableParagraphStyle?
    
    init(text: String?) {
        self.text = text
    }
    
    func foregroundColor(_ color: UIColor) -> JCAttributedStringBuilder {
        attributes[.foregroundColor] = color
        return self
    }
    func font(_ font: UIFont) -> JCAttributedStringBuilder {
        attributes[.font] = font
        return self
    }
    func shadow(color: UIColor, blurRadius: CGFloat, offset: CGSize) -> JCAttributedStringBuilder {
        if shadow == nil {
            shadow = NSShadow()
        }
        shadow?.shadowColor = color
        shadow?.shadowBlurRadius = blurRadius
        shadow?.shadowOffset = offset
        return self
    }
    func shadowColor(_ color: UIColor) -> JCAttributedStringBuilder {
        if shadow == nil {
            shadow = NSShadow()
        }
        shadow?.shadowColor = color
        return self
    }
    func shadowBlurRadius(_ blurRadius: CGFloat) -> JCAttributedStringBuilder {
        if shadow == nil {
            shadow = NSShadow()
        }
        shadow?.shadowBlurRadius = blurRadius
        return self
    }
    func shadowOffset(_ offset: CGSize) -> JCAttributedStringBuilder {
        if shadow == nil {
            shadow = NSShadow()
        }
        shadow?.shadowOffset = offset
        return self
    }
    func paragraphStyle(lineSpacing: CGFloat, alignment: NSTextAlignment, lineBreakMode: NSLineBreakMode) -> JCAttributedStringBuilder {
        if paragraphStyle == nil {
            paragraphStyle = NSMutableParagraphStyle()
        }
        paragraphStyle?.lineSpacing = lineSpacing
        paragraphStyle?.alignment = alignment
        paragraphStyle?.lineBreakMode = lineBreakMode
        return self
    }
    func paragraphStyleLineSpacing(_ value: CGFloat) -> JCAttributedStringBuilder {
        if paragraphStyle == nil {
            paragraphStyle = NSMutableParagraphStyle()
        }
        paragraphStyle?.lineSpacing = value
        return self
    }
    func paragraphStyleAlignment(_ alignment: NSTextAlignment) -> JCAttributedStringBuilder {
        if paragraphStyle == nil {
            paragraphStyle = NSMutableParagraphStyle()
        }
        paragraphStyle?.alignment = alignment
        return self
    }
    func paragraphStyleLineBreakMode(_ lineBreakMode: NSLineBreakMode) -> JCAttributedStringBuilder {
        if paragraphStyle == nil {
            paragraphStyle = NSMutableParagraphStyle()
        }
        paragraphStyle?.lineBreakMode = lineBreakMode
        return self
    }
    
    func build() -> NSAttributedString? {
        guard let text = text, !text.isEmpty else { return nil }
        if let shadow = self.shadow {
            attributes[.shadow] = shadow
        }
        if let paragraphStyle = self.paragraphStyle {
            attributes[.paragraphStyle] = paragraphStyle
        }
        return NSAttributedString(string: text, attributes: attributes)
    }
    func buildUnpack() -> NSAttributedString {
        if let shadow = self.shadow {
            attributes[.shadow] = shadow
        }
        if let paragraphStyle = self.paragraphStyle {
            attributes[.paragraphStyle] = paragraphStyle
        }
        return NSAttributedString(string: text ?? " ", attributes: attributes)
    }
}

// MARK: - UI
protocol JCUIBuilder {
    associatedtype InstanceType: UIView
    
    var instance: InstanceType { get set }
    
    func backgroundColor(_ color: UIColor) -> Self
    func isHidden(_ isHidden: Bool) -> Self
    func alpha(_ alpha: CGFloat) -> Self
    func clipsToBounds(_ isTO: Bool) -> Self
    
    func build() -> InstanceType
    func build(withFrame frame: CGRect) -> InstanceType
}
extension JCUIBuilder {
    func backgroundColor(_ color: UIColor) -> Self {
        instance.backgroundColor = color
        return self
    }
    func isHidden(_ isHidden: Bool) -> Self {
        instance.isHidden = isHidden
        return self
    }
    func alpha(_ alpha: CGFloat) -> Self {
        instance.alpha = alpha
        return self
    }
    func clipsToBounds(_ isTO: Bool) -> Self {
        instance.clipsToBounds = isTO
        return self
    }
    func build() -> InstanceType {
        return instance
    }
    func build(withFrame frame: CGRect) -> InstanceType {
        instance.frame = frame
        return instance
    }
}
// MARK: View
class JCViewBuilder: JCUIBuilder {
    internal var instance: UIView
    
    init() {
        instance = UIView(frame: .zero)
    }
}
// MARK: UIImageView
class JCImageViewBuilder: JCUIBuilder {
    var instance: UIImageView
    
    init() {
        instance = UIImageView(frame: .zero)
    }
    func contentMode(_ contentMode: UIView.ContentMode) -> JCImageViewBuilder {
        instance.contentMode = contentMode
        return self
    }
    func image(_ image: UIImage?) -> JCImageViewBuilder {
        instance.image = image
        return self
    }
    func image(named: String) -> JCImageViewBuilder {
        instance.image = UIImage(named: named)
        return self
    }
}
// MARK: Button
class JCButtonBuilder: JCUIBuilder {
    
    var instance: UIButton
    
    init(_ type: UIButton.ButtonType) {
        self.instance = UIButton(type: type)
    }
    
    func title(_ text: String, for state: UIControl.State = UIControl.State()) -> JCButtonBuilder {
        instance.setTitle(text, for: state)
        return self
    }
    
    func titleColor(_ color: UIColor, for state: UIControl.State = UIControl.State()) -> JCButtonBuilder {
        instance.setTitleColor(color, for: state)
        return self
    }
    
    func font(_ font: UIFont) -> JCButtonBuilder {
        instance.titleLabel?.font = font
        return self
    }
    
    func target(_ target: Any?, action: Selector, for event: UIControl.Event = .touchUpInside) -> JCButtonBuilder {
        instance.addTarget(target, action: action, for: event)
        return self
    }
    
    func image(_ image: UIImage?, for state: UIControl.State = UIControl.State()) -> JCButtonBuilder {
        instance.setImage(image, for: state)
        return self
    }
    
    func attributedText(_ text: NSAttributedString?) -> JCButtonBuilder {
        instance.setAttributedTitle(text, for: UIControl.State())
        return self
    }
}
// MARK: Label
class JCLabelBuilder: JCUIBuilder {
    var instance: UILabel
    
    init() {
        self.instance = UILabel(frame: .zero)
    }
    
    func text(_ text: String) -> JCLabelBuilder {
        instance.text = text
        return self
    }
    func textColor(_ color: UIColor) -> JCLabelBuilder {
        instance.textColor = color
        return self
    }
    func font(_ font: UIFont) -> JCLabelBuilder {
        instance.font = font
        return self
    }
    func attributedText(_ text: NSAttributedString) -> JCLabelBuilder {
        instance.attributedText = text
        return self
    }
    func textAlignment(_ alignment: NSTextAlignment) -> JCLabelBuilder {
        instance.textAlignment = alignment
        return self
    }
}
